package handler

import (
	"context"
	"io"

	"gitee.com/bjf-fhe/apicat/entry"
	"gitee.com/bjf-fhe/apicat/errors"
	"gitee.com/bjf-fhe/apicat/source"
	"github.com/getkin/kin-openapi/openapi3"
	"github.com/sirupsen/logrus"
)

type Handlers struct {
	EntryHandlers []EntryHandler
	SumHandlers   []SumHandler
	Ctx           context.Context
}

type EntryHandler interface {
	RecordEntry(en *entry.LogEntry) error
}

type SumHandler interface {
	Sum() error
	RecordError(err error) error
}

func (hs *Handlers) Handle(reader source.Reader, cfg entry.ConfigDetector, api *openapi3.T, baseUrl string) error {
	//t.Lines is a channel

readLoop:
	for {
		select {
		case <-hs.Ctx.Done():
			logrus.Info("读取被取消")
			break readLoop
		case recAndError := <-reader.Records():
			// rec, err := reader.Read()
			rec := recAndError.Entry
			err := recAndError.Error.Error
			if err == io.EOF {
				if cfg.IsSub() {
					logrus.Errorln("读取EOF")
					//直接返回，不需要执行sum，因为sum是在上层执行的，这里只负责在EOF时退出
					return io.EOF
				} else if cfg.IsMain() {
					//这只是某一个子节点的EOF，不需要退出，只需要继续读取
					continue
				} else {
					logrus.Info("读取EOF")
					break readLoop
				}
			} else if err != nil {
				for i := 0; i < len(hs.SumHandlers); i++ {
					err = hs.SumHandlers[i].RecordError(err)
					if err != nil {
						return err
					}
				}
				return errors.Wrap(err, errors.SourceReadError)
			}
			rec.DetechError(cfg, api, baseUrl)
			//else rec.Legal = false
			for i := 0; i < len(hs.EntryHandlers); i++ {
				err = hs.EntryHandlers[i].RecordEntry(rec)
				if err != nil {
					return err
				}
			}
		}
	}

	for i := 0; i < len(hs.SumHandlers); i++ {
		err := hs.SumHandlers[i].Sum()
		if err != nil {
			return err
		}
	}

	return nil
}

func NewHandlers(ctx context.Context, handlers ...interface{}) *Handlers {

	var hs Handlers

	hs.Ctx = ctx

	for i := 0; i < len(handlers); i++ {
		switch handlers[i].(type) {
		case EntryHandler:
			hs.EntryHandlers = append(hs.EntryHandlers, handlers[i].(EntryHandler))
		case SumHandler:
			hs.SumHandlers = append(hs.SumHandlers, handlers[i].(SumHandler))
		default:
			logrus.WithField("type", handlers[i]).Error("未知的handler类型")
		}
	}
	return &hs
}
